#include "filemover.h"

FileMover::FileMover(std::string sourceDir, std::string targetDir) noexcept
    : _sourceDir(sourceDir), _targetDir(targetDir)
{
#ifdef LOG
    std::cout << "[INFO] FileMover initialisation successful" << std::endl;
    std::cout << "[INFO] Source directory: " << _sourceDir << std::endl;
    std::cout << "[INFO] Target directory: " << _targetDir << std::endl;
#endif // LOG
}

FileMover::~FileMover() noexcept
{
}

bool FileMover::IsExist(const std::string &path) noexcept
{
    return std::filesystem::exists(path);
}

bool FileMover::CreateDir(const std::string &dir)
{
    try
    {
        return std::filesystem::create_directories(dir);
    }
    catch (const std::exception &e)
    {
        throw e;
    }
}

time_t FileMover::GetFileFixedTime(const std::string &path)
{
    try
    {
        std::filesystem::file_time_type time = std::filesystem::last_write_time(path);
        return time.time_since_epoch().count();
    }
    catch (const std::exception &e)
    {
        throw e;
    }
}

std::string &FileMover::sourceDir()
{
    return _sourceDir;
}

const std::string &FileMover::sourceDir() const
{
    return _sourceDir;
}

std::string &FileMover::targetDir()
{
    return _targetDir;
}

const std::string &FileMover::targetDir() const
{
    return _targetDir;
}

bool FileMover::move()
{
    try
    {
        if (!IsExist(_sourceDir))
        {
#ifdef LOG
            std::cout << "[ERROR] The source directory does not exist" << std::endl;
#endif // LOG
            return false;
        }
        if (!IsExist(_targetDir))
        {
#ifdef LOG
            std::cout << "[WARNIG] The target directory does not exist" << std::endl;
#endif // LOG
            CreateDir(_targetDir);
#ifdef LOG
            std::cout << "[INFO] Target directory has been created" << std::endl;
#endif // LOG
        }
        // Get all files from _sourceDir and sort by time
        std::filesystem::path sourceDir(_sourceDir);
#ifdef LOG
        std::cout << "[INFO] Start to find all files" << std::endl;
#endif // LOG
        for (const auto &nowFile : std::filesystem::directory_iterator(sourceDir))
        {
            if (nowFile.is_regular_file())
            {
                _timeSortedfileNames.push_back(nowFile.path().string());
            }
        }
#ifdef LOG
        std::cout << "[INFO] All files have been found" << std::endl;
        std::cout << "[INFO] Total number of files: " << _timeSortedfileNames.size() << std::endl;
        std::cout << "[INFO] Start to sort files by time" << std::endl;
#endif // LOG
        std::sort(_timeSortedfileNames.begin(),
                  _timeSortedfileNames.end(),
                  [](const std::string &a, const std::string &b)
                  { return GetFileFixedTime(a) < GetFileFixedTime(b); });
#ifdef LOG
        std::cout << "[INFO] All files have been sorted" << std::endl;
        std::cout << "[INFO] Start to copy files" << std::endl;
#endif // LOG
       // Copy files one by one
        for (const auto &nowFile : _timeSortedfileNames)
        {
            // Overwrite existing
            std::filesystem::copy(nowFile, _targetDir, std::filesystem::copy_options::overwrite_existing);
#ifdef LOG
            std::cout << "[INFO] " << nowFile << " has been copied" << std::endl;
#endif // LOG
        }
#ifdef LOG
        std::cout << "[INFO] All files have been copied" << std::endl;
#endif // LOG
        return true;
    }
    catch (const std::exception &e)
    {
        throw e;
    }
}